package com.Prot2.Logger;

import java.io.File;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.provider.Settings;
import android.util.Log;
import android.widget.Toast;

import com.Prot2.Globals;

public class CoordinatorContinuous extends Service {

		private static final String TAG = "Coordinator";
		protected static final String DELIMITER = ",";
		private Context context;
		private		Timer tFile,tDataBuffer,tRecognition;
		private Handler balanceLogHandler;
		private Handler toggleHandler;
		
		public void onCreate(){
			context=this;
			super.onCreate();
			
			//TODO monitor changes to this string...
			String providers = Settings.Secure.getString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
			Log.w(TAG,"GPS: "+providers);
			
			Log.w(TAG,"Service created, fp: "+Globals.logFilePath);
			
			startThreads();
			Globals.recognitionWorker = new RecognitionWorker(context);

			
			//*///////////////////////////////////////////FILE LOGGING////////////////////////////////////////////////////////////////////
			Globals.logFilePath=Globals.dirPath+"log_"+Globals.getDateAndTimeStamp()+".txt";
			Globals.createLogFile();
			Globals.makeFileEntry(Globals.logHeader(DELIMITER),Globals.logFile);
			tFile = new Timer();
			tFile.scheduleAtFixedRate(new LogEntry(), 0, Globals.samplingRate);
			//*////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			
			//*///////////////////////////////////////////ARRAY LOGGING/////////////////////////////////////////////////////////////////////
			Globals.dataTable = new double [7][Globals.samplingTime/Globals.samplingRate];
			tDataBuffer = new Timer();
			tDataBuffer.scheduleAtFixedRate(new ContinuousDataTable(), 0, Globals.samplingTime+Globals.waitTime); //wait time can be adjusted to run recognitions less/more frequently. It also serves as a buffer to make up for interrupts from the OS-level.
			//*/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			
			
			//*///////////////////////////////////////////GPS & WIFI TOGGLING/////////////////////////////////////////////////////////////////////
//			
//			
//			toggleHandler = new Handler();
//			toggleHandler.postDelayed(toggleRunnable, Globals.contextToggleInterval);
			//*/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			
			
			
			
			//*///////////////////////////////////////////Balance LOGGING/////////////////////////////////////////////////////////////////////
			Globals.createBalanceFile();
			
			balanceLogHandler = new Handler();
			balanceLogHandler.postDelayed(balanceLogRunnable, Globals.samplingTime+Globals.waitTime);
			//*/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			
			Toast.makeText(this, "started logging" ,Toast.LENGTH_SHORT).show();
		}
		
		
		private Runnable toggleRunnable = new Runnable(){
			@Override
			public void run(){
				if(Globals.currentlyDetectedLabel!=Globals.currentlyEstablishedLabel){
					
					if(Globals.currentlyDetectedLabel==Globals.previouslyDetectedLabel){
						Globals.contextSteady++;
						if(Globals.contextSteady>Globals.contextSteadyRequired){
							Globals.currentlyEstablishedLabel=Globals.currentlyDetectedLabel;
							ToggleWorker.toggle(context);
							Globals.contextSteady=0;
						}
					}
				}
				toggleHandler.postDelayed(toggleRunnable,Globals.contextToggleInterval);
			}
		};
		
		private Runnable balanceLogRunnable = new Runnable(){
			@Override
			public void run(){
				String str = balanceEntry(DELIMITER);
				Globals.makeFileEntry(str, Globals.balanceFile);
				Log.w(TAG,"updating balance log file");
				balanceLogHandler.postDelayed(balanceLogRunnable, Globals.samplingTime+Globals.waitTime);
			}
		};
		
		private String balanceEntry(String DELIMITER){
			Globals.now.setToNow();
			return ""+Globals.now.format3339(false)
					 +DELIMITER+Globals.currentlyDetectedLabel
					 +DELIMITER+Globals.batteryWorker.getRead(DELIMITER)
					 +System.getProperty("line.separator");
		}
		
		
		
		
		private void startThreads(){
			Globals.accelerationWorker = new AccelerationWorker(context);
			//Globals.gyroWorker = new GyroWorker(context);
			Globals.lightWorker = new LightWorker(context);
			Globals.humidityWorker = new HumidityWorker(context);
			Globals.temperatureWorker = new TemperatureWorker(context);
			Globals.pressureWorker = new PressureWorker(context);
			Globals.gpsWorker = new GPSWorker(context);
			Globals.wifiWorker = new WiFiWorker(context);
			Globals.batteryWorker = new BatteryWorker(context);
		}
		
		private void stopThreads(){
			Globals.accelerationWorker.stop();
			//Globals.gyroWorker.stop();
			Globals.lightWorker.stop();
			Globals.humidityWorker.stop();
			Globals.temperatureWorker.stop();
			Globals.pressureWorker.stop();
			Globals.gpsWorker.stop();
			Globals.wifiWorker.stop();
			Globals.batteryWorker.stop(context);	
//			tFile.cancel();
			tDataBuffer.cancel();
			balanceLogHandler.removeCallbacks(balanceLogRunnable);
			
		}
		
		public void onDestroy(){
			stopThreads();
			Globals.dirPath=Environment.getExternalStorageDirectory()+"/"+Globals.appPath+"/DATA/"+Globals.getLogFolder()+"/";
		//	Globals.logFilePath=Globals.dirPath+"logfile.txt";
			Toast.makeText(this, "stopped logging" ,Toast.LENGTH_SHORT).show();
		}
		
		
		
		@Override
		public IBinder onBind(Intent arg0) {
			// TODO Auto-generated method stub
			return null;
		}
		
		
		

		private class LogEntry extends TimerTask{
			
			private String logEntry(String DELIMITER){
				Globals.now.setToNow();
				return ""+System.currentTimeMillis()
						 +DELIMITER+Globals.now.hour+":"+Globals.now.minute+":"+Globals.now.second
						 +DELIMITER+Globals.accelerationWorker.getRead(DELIMITER)
						// +DELIMITER+Globals.gyroWorker.getRead(DELIMITER)
						 +DELIMITER+Globals.lightWorker.getRead(DELIMITER)
						 +DELIMITER+Globals.humidityWorker.getRead(DELIMITER)
						 +DELIMITER+Globals.temperatureWorker.getRead(DELIMITER)
						 +DELIMITER+Globals.pressureWorker.getRead(DELIMITER)
						 +DELIMITER+Globals.currentLocationTag
						 +DELIMITER+Globals.gpsWorker.getRead(DELIMITER)
						 +DELIMITER+Globals.wifiWorker.getRead(DELIMITER)
						 +DELIMITER+Globals.batteryWorker.getRead(DELIMITER)
						 +System.getProperty("line.separator");
			}
			
			@Override
			public void run() {
				//make a log entry..
			
				String str = logEntry(DELIMITER);
//				Log.w(TAG,"making log entry: "+str);			logging debug
			
				Globals.makeFileEntry(str, Globals.logFile);
			

			}
			
		}
			
		
		
		private class ContinuousDataTable extends TimerTask{
			
			public void run(){
				Timer t1=new Timer();
				
//				Log.w(TAG,Globals.dataTable[0][10]+"");
//				Log.w(TAG,Globals.dataTable[1][10]+"");
//				Log.w(TAG,Globals.dataTable[2][10]+"");
//				Log.w(TAG,Globals.dataTable[3][10]+"");
//				Log.w(TAG,Globals.dataTable[4][10]+"");
//				Log.w(TAG,Globals.dataTable[5][10]+"");
//				Log.w(TAG,Globals.dataTable[6][10]+"");

				
				Globals.dataTableCounter=0;
//				Log.w(TAG,"Generating new buffertable");
				Globals.dataTable = new double [7][Globals.samplingTime/Globals.samplingRate];
				t1.scheduleAtFixedRate(new BufferUpdate(), 0, Globals.samplingRate);

				
			}
			
			private class BufferUpdate	extends TimerTask{
			
				private static final String TAG = "RecognitionWorker";

				public void run(){
					if(Globals.dataTableCounter<Globals.samplingTime/Globals.samplingRate){
						Globals.dataTable[0][Globals.dataTableCounter]=Globals.accelerationWorker.getXAcc();
						Globals.dataTable[1][Globals.dataTableCounter]=Globals.accelerationWorker.getYAcc();
						Globals.dataTable[2][Globals.dataTableCounter]=Globals.accelerationWorker.getZAcc();
						Globals.dataTable[3][Globals.dataTableCounter]=Globals.lightWorker.getLux();
						Globals.dataTable[4][Globals.dataTableCounter]=Globals.humidityWorker.getRH();
						Globals.dataTable[5][Globals.dataTableCounter]=Globals.temperatureWorker.getTemp();
						Globals.dataTable[6][Globals.dataTableCounter]=Globals.pressureWorker.getPress();
						//TODO other entries as well
						Globals.dataTableCounter ++;
					}else{
						Globals.recognitionWorker.evaluateDataTable(Globals.dataTable,Globals.samplingTime,Globals.samplingRate);
						this.cancel();
					}
				}		
			}	
		
		}
		
	}
